Import and format data
Import IPUMS
Use of data from IPUMS USA is subject to conditions including that users should
cite the data appropriately. Use command `ipums_conditions()` for more details.
|= | 1% 6 MB
|=== | 3% 13 MB
|===== | 5% 19 MB
|======= | 7% 26 MB
|========= | 9% 32 MB
|=========== | 10% 39 MB
|============= | 12% 45 MB
|=============== | 14% 52 MB
|================= | 16% 58 MB
|=================== | 18% 65 MB
|===================== | 19% 71 MB
|======================= | 21% 78 MB
|========================= | 23% 84 MB
|=========================== | 25% 91 MB
|============================ | 27% 97 MB
|============================== | 28% 104 MB
|================================ | 30% 110 MB
|================================== | 32% 117 MB
|==================================== | 34% 123 MB
|====================================== | 36% 130 MB
|======================================== | 37% 136 MB
|========================================== | 39% 143 MB
|============================================ | 41% 149 MB
|============================================== | 43% 156 MB
|================================================ | 45% 162 MB
|================================================== | 46% 169 MB
|==================================================== | 48% 175 MB
|====================================================== | 50% 182 MB
|======================================================= | 52% 188 MB
|========================================================= | 54% 195 MB
|=========================================================== | 55% 201 MB
|============================================================= | 57% 208 MB
|=============================================================== | 59% 214 MB
|================================================================= | 61% 221 MB
|=================================================================== | 63% 227 MB
|===================================================================== | 64% 234 MB
|======================================================================= | 66% 240 MB
|========================================================================= | 68% 247 MB
|=========================================================================== | 70% 253 MB
|============================================================================= | 72% 260 MB
|=============================================================================== | 73% 266 MB
|================================================================================= | 75% 273 MB
|================================================================================== | 77% 279 MB
|==================================================================================== | 79% 286 MB
|====================================================================================== | 81% 292 MB
|======================================================================================== | 82% 299 MB
|========================================================================================== | 84% 305 MB
|============================================================================================ | 86% 312 MB
|============================================================================================== | 88% 318 MB
|================================================================================================ | 90% 325 MB
|================================================================================================== | 91% 331 MB
|==================================================================================================== | 93% 338 MB
|====================================================================================================== | 95% 344 MB
|======================================================================================================== | 97% 351 MB
|==========================================================================================================| 99% 357 MB
|===========================================================================================================| 100% 360 MB
PUMA shapefiles
OGR data source with driver: ESRI Shapefile
Source: "/Users/chriszs/Desktop/work/covid-immigrant-foodworkers/data/ipums_puma_2010/ipums_puma_2010.shp", layer: "ipums_puma_2010"
with 2378 features
It has 7 fields
Integer64 fields read as strings: GISMATCH
County shapefiles
OGR data source with driver: ESRI Shapefile
Source: "/Users/chriszs/Desktop/work/covid-immigrant-foodworkers/data/tl_2019_us_county/tl_2019_us_county.shp", layer: "tl_2019_us_county"
with 3233 features
It has 17 fields
Integer64 fields read as strings: ALAND AWATER
COVID county cases and deaths
covid <- read_csv("data/us-counties.csv",
col_types = cols(.default = "?", date = "D")) %>%
rename(county_code = fips) %>%
# Filter to the latest data for each county
group_by(county_code) %>%
slice(which.max(date))
covid
County populations
Read-in Census API key
census_key <- (readLines(key_file)[1])
Create list of all US states to iterate through in the API calls
us <- unique(fips_codes$state)[1:51]
us
[1] "AL" "AK" "AZ" "AR" "CA" "CO" "CT" "DE" "DC" "FL" "GA" "HI" "ID" "IL" "IN" "IA" "KS" "KY" "LA" "ME" "MD" "MA" "MI"
[24] "MN" "MS" "MO" "MT" "NE" "NV" "NH" "NJ" "NM" "NY" "NC" "ND" "OH" "OK" "OR" "PA" "RI" "SC" "SD" "TN" "TX" "UT" "VT"
[47] "VA" "WA" "WV" "WI" "WY"
Download population data from the 2014-2018 ACS
PUMA-to-county crosswalk
county_to_puma_crosswalk <- read_csv("data/geocorr2018.csv", skip = 1) %>%
mutate(puma_code = paste0(`State code`, `PUMA (2012)`)) %>%
select(
puma_code,
county_code = `County code (2014)`,
state = `State abbreviation`,
county = `2014 county name`,
puma = `PUMA12 name`,
allocation_factor = `puma12 to county14 allocation factor`
)
county_to_puma_crosswalk
Join the COVID, population and crosswalk data frames
crosswalk <- list(covid, population, county_to_puma_crosswalk) %>%
reduce(full_join, by = "county_code") %>%
mutate(
puma = paste(puma, state.x, sep = ", "),
cases_per_100k = round(cases / population * 100000, digits = 0),
deaths_per_100k = round(deaths / population * 100000, digits = 0)
) %>%
select(
1,
state = state.x,
county_code,
county = county.y,
puma_code,
puma,
population,
cases,
deaths,
cases_per_100k,
deaths_per_100k,
allocation_factor
)
crosswalk
Filter to the food production industries we’re interested in
food_production_industries <-
list("0170", # Crop production
"0180", # Animal production and aquaculture
"0290", # Support activities for agriculture and forestry
"1070", # Animal food, grain and oilseed milling
"1080", # Sugar and confectionery products
"1090", # Fruit and vegetable preserving and specialty food manufacturing
"1170", # Dairy product manufacturing
"1180", # Animal slaughtering and processing
"1270", # Bakeries and tortilla manufacturing, except retail bakeries
"1280", # Seafood and other miscellaneous foods; n.e.c.
"1290") # Not specified food industries
ipums_food_production <- ipums %>%
filter(industry_code %in% food_production_industries)
Calculate employment by industry-occupation grouping
ipums_food_production_employment_by_ind_occ <-
ipums_food_production %>%
group_by(industry, occupation) %>%
summarize(num_employees = sum(PERWT)) %>%
pivot_wider(
id_cols = c(industry, occupation),
values_from = num_employees,
names_prefix = "num_employees"
) %>%
replace(is.na(.), 0) %>%
# Exclude from our analysis ind-occ groupings
# with fewer than 2,500 employees nationally
filter(num_employees >= 2500)
Export the data
write_csv(
ipums_food_production_employment_by_ind_occ,
"data/exported/ipums_food_production_employment_by_ind_occ.csv"
)
Filter the industry-occupation pairs
Import data frame of food production industry-occupation pairs
ipums_food_production_employment_by_ind_occ <-
read_csv("data/ipums_food_production_total_employment_by_ind_occ.csv")
Join the industry-occupation pairs to the ipums data and filter to just the industry-occupation pairs we want
ipums_food_production_selected_occupations <-
ipums_food_production %>%
inner_join(ipums_food_production_employment_by_ind_occ,
by = c("industry", "occupation")) %>%
filter(exclude == FALSE) %>%
select(-num_employees, -exclude)
ipums_food_production_selected_occupations
And join with the pumas data frame to get the PUMA names
ipums_food_production_selected_occupations <-
ipums_food_production_selected_occupations %>%
left_join(pumas, by = "puma_code") %>%
mutate(puma = paste(puma, state, sep = ", ")) %>%
select(1:3,
13,
4:12)
ipums_food_production_selected_occupations
citizenship_lookup = tibble(
citizenship_code = factor(c(
0, 1, 2, 3, 4, 5
)),
citizenship = c(
"native_citizen", # n/a
"native_citizen", # born_abroad_citizen
"naturalized_citizen", # naturalized_citizen
"non_citizen", # non_citizen
"non_citizen_with_papers", # non_citizen_with_papers
"foreign_born_status_unknown"
)
)
ethnicity_lookup = tibble(
ethnicity_code = factor(c(
0, 1, 2, 3, 4, 9
)),
ethnicity = c(
"non_hispanic",
"hispanic", # mexican
"hispanic", # puerto_rican
"hispanic", # cuban
"hispanic", # other
"not_reported"
)
)
ipums_food_production_selected_occupations_mapped <-
ipums_food_production_selected_occupations %>%
select(-ethnicity,-citizenship) %>%
left_join(ethnicity_lookup, by="ethnicity_code") %>%
left_join(citizenship_lookup, by="citizenship_code")
pct <- function (part,whole) {
round(part / whole * 100, digits = 0)
}
calc_percents <- function (rows) {
rows %>%
mutate(
total_native_citizen = (
total_native_citizen_non_hispanic +
total_native_citizen_hispanic
),
total_naturalized_citizen = (
total_naturalized_citizen_non_hispanic +
total_naturalized_citizen_hispanic
),
total_non_citizen = (
total_non_citizen_non_hispanic +
total_non_citizen_hispanic
),
total_foreign_non_hispanic = (
total_naturalized_citizen_non_hispanic +
total_non_citizen_non_hispanic
),
total_foreign_hispanic = (
total_naturalized_citizen_hispanic +
total_non_citizen_hispanic
),
total_foreign = (
total_foreign_non_hispanic +
total_foreign_hispanic
),
total_employees = (
total_native_citizen +
total_naturalized_citizen +
total_non_citizen
),
pct_native_citizen_non_hispanic =
pct(total_native_citizen_non_hispanic, total_employees),
pct_native_citizen_hispanic =
pct(total_native_citizen_hispanic, total_employees),
pct_total_foreign_non_hispanic =
pct(total_foreign_non_hispanic, total_employees),
pct_total_foreign_hispanic =
pct(total_foreign_hispanic, total_employees),
pct_naturalized_citizen_non_hispanic =
pct(total_naturalized_citizen_non_hispanic, total_employees),
pct_naturalized_citizen_hispanic =
pct(total_naturalized_citizen_hispanic, total_employees),
pct_non_citizen_non_hispanic =
pct(total_non_citizen_non_hispanic, total_employees),
pct_non_citizen_hispanic =
pct(total_non_citizen_hispanic, total_employees),
pct_native_citizen =
pct(total_native_citizen, total_employees),
pct_total_foreign =
pct(total_foreign, total_employees),
pct_naturalized_citizen =
pct(total_naturalized_citizen, total_employees),
pct_non_citizen =
pct(total_non_citizen, total_employees)
)
}
ipums_food_production_selected_occupations_mapped
Calculate the national-level citizenship and ethnicity data for these industry-occupation pairs
ipums_food_production_by_industry_occupation <-
ipums_food_production_selected_occupations_mapped %>%
group_by(industry_code,
industry,
occupation_code,
occupation,
citizenship,
ethnicity) %>%
summarize(num_employees = sum(PERWT)) %>%
pivot_wider(
id_cols = c(industry_code, industry, occupation_code, occupation),
names_from = c(citizenship, ethnicity),
values_from = num_employees,
names_prefix = "total_"
) %>%
replace(is.na(.), 0) %>%
calc_percents()
ipums_food_production_by_industry_occupation
Export the data
write_csv(
ipums_food_production_by_industry_occupation,
"data/exported/ipums_food_production_by_industry_occupation.csv"
)
Group the data by PUMA
ipums_food_production_by_puma <-
ipums_food_production_selected_occupations_mapped %>%
group_by(state_code,
state,
puma_code,
puma,
citizenship,
ethnicity) %>%
summarize(num_employees = sum(PERWT, na.rm = TRUE)) %>%
pivot_wider(
id_cols = c(state_code, state, puma_code, puma),
names_from = c(citizenship, ethnicity),
values_from = num_employees,
names_prefix = "total_"
) %>%
replace(is.na(.), 0) %>%
calc_percents()
ipums_food_production_by_puma %>% select(puma_code,total_foreign)
Export the data
write_csv(
ipums_food_production_by_puma,
"data/exported/ipums_food_production_by_puma.csv"
)
Group the data by PUMA and industry and occupation
ipums_food_production_by_puma_ind_occ <-
ipums_food_production_selected_occupations_mapped %>%
group_by(
state_code,
state,
puma_code,
puma,
industry_code,
industry,
occupation_code,
occupation,
citizenship,
ethnicity
) %>%
summarize(num_employees = sum(PERWT)) %>%
pivot_wider(
id_cols = c(
state_code,
state,
puma_code,
puma,
industry_code,
industry,
occupation_code,
occupation
),
names_from = c(citizenship, ethnicity),
values_from = num_employees,
names_prefix = "total_"
) %>%
replace(is.na(.), 0) %>%
calc_percents()
Export the data
write_csv(
ipums_food_production_by_puma_ind_occ,
"data/exported/ipums_food_production_by_puma_ind_occ.csv"
)
ipums_food_production_by_puma
Join the employment data to the crosswalk data frame
ipums_food_production_by_puma
ipums_food_production_by_puma_crosswalked_to_county <-
ipums_food_production_by_puma %>%
left_join(crosswalk, by = "puma_code") %>%
mutate(
total_employees = round(
total_employees * allocation_factor,
digits = 0
),
total_native_citizen_non_hispanic = round(total_native_citizen_non_hispanic *
allocation_factor, digits = 0),
total_native_citizen_hispanic = round(total_native_citizen_hispanic *
allocation_factor, digits = 0),
total_foreign_non_hispanic = round(total_foreign_non_hispanic *
allocation_factor, digits = 0),
total_foreign_hispanic = round(total_foreign_hispanic *
allocation_factor, digits = 0),
total_naturalized_citizen_non_hispanic = round(total_naturalized_citizen_non_hispanic
* allocation_factor, digits = 0),
total_naturalized_citizen_hispanic = round(total_naturalized_citizen_hispanic
* allocation_factor, digits = 0),
total_non_citizen_non_hispanic = round(total_non_citizen_non_hispanic
* allocation_factor, digits = 0),
total_non_citizen_hispanic = round(total_non_citizen_hispanic
* allocation_factor, digits = 0),
total_native_citizen = total_native_citizen_non_hispanic + total_native_citizen_hispanic,
total_foreign = total_foreign_non_hispanic + total_foreign_hispanic,
total_naturalized_citizen = total_naturalized_citizen_non_hispanic +
total_naturalized_citizen_hispanic,
total_non_citizen = total_non_citizen_non_hispanic + total_non_citizen_hispanic
) %>%
select(1,
state = state.x,
3,
puma = puma.x,
32:33,
35:40,
5:17)
ipums_food_production_by_puma_crosswalked_to_county
ipums_food_production_by_puma_crosswalked_to_county %>% filter(county_code == "06053") %>% select(allocation_factor, total_employees, total_foreign, total_non_citizen)
Join the employment data to the crosswalk data frame
ipums_food_production_by_puma_ind_occ_crosswalked_to_county <-
ipums_food_production_by_puma_ind_occ %>%
left_join(crosswalk, by = "puma_code") %>%
mutate(
total_employees = round(
total_employees * allocation_factor,
digits = 0
),
total_native_citizen_non_hispanic = round(total_native_citizen_non_hispanic
* allocation_factor, digits = 0),
total_native_citizen_hispanic = round(total_native_citizen_hispanic
* allocation_factor, digits = 0),
total_foreign_non_hispanic = round(total_foreign_non_hispanic
* allocation_factor, digits = 0),
total_foreign_hispanic = round(total_foreign_hispanic
* allocation_factor, digits = 0),
total_naturalized_citizen_non_hispanic = round(total_naturalized_citizen_non_hispanic
* allocation_factor, digits = 0),
total_naturalized_citizen_hispanic = round(total_naturalized_citizen_hispanic
* allocation_factor, digits = 0),
total_non_citizen_non_hispanic = round(total_non_citizen_non_hispanic
* allocation_factor, digits = 0),
total_non_citizen_hispanic = round(total_non_citizen_hispanic
* allocation_factor, digits = 0),
total_native_citizen = total_native_citizen_non_hispanic + total_native_citizen_hispanic,
total_foreign = total_foreign_non_hispanic + total_foreign_hispanic,
total_naturalized_citizen = total_naturalized_citizen_non_hispanic +
total_naturalized_citizen_hispanic,
total_non_citizen = total_non_citizen_non_hispanic + total_non_citizen_hispanic
) %>%
select(1,
state = state.x,
3,
puma = puma.x,
36:37,
5:8,
39:44,
9:21)
ipums_food_production_by_puma_crosswalked_to_county
Group the data by county
# This step is required to deal with situations
# where multiple PUMAs split a single county
ipums_food_production_by_county <-
ipums_food_production_by_puma_crosswalked_to_county %>%
group_by(state_code, state, county_code, county) %>%
calc_percents()
Export the data
write_csv(
ipums_food_production_by_county,
"data/exported/ipums_food_production_by_county.csv"
)
Group the data by industry and occupation and county
ipums_food_production_by_puma_ind_occ_crosswalked_to_county
# This step is required to deal with situations
# where multiple PUMAs split a single county
ipums_food_production_by_county_ind_occ <-
ipums_food_production_by_puma_ind_occ_crosswalked_to_county %>%
group_by(
state_code,
state,
county_code,
county,
industry_code,
industry,
occupation_code,
occupation
) %>%
calc_percents()
ipums_food_production_by_county_ind_occ
Export the data
write_csv(
ipums_food_production_by_county_ind_occ,
"data/exported/ipums_food_production_by_county_ind_occ.csv"
)
Analyze the data
What is the total number of workers employed in these industries?
sum(ipums_food_production_by_puma$total_employees)
What is the total number of foreigners employed in these industries?
sum(ipums_food_production_by_puma$total_foreign)
What’s that as a percent?
sum(ipums_food_production_by_puma$total_foreign) /
sum(ipums_food_production_by_puma$total_employees) * 100
How many of the jobs have a higher proportion of foreigners employed than the national average of 17.1%?
ipums_food_production_by_industry_occupation %>%
filter(pct_total_foreign > 17.1) %>%
select(
industry,
occupation,
total_employees,
pct_total_foreign,
pct_total_foreign_hispanic
) %>%
arrange(desc(total_employees))
What is the total number of Hispanic foreigners employed in these industries?
sum(ipums_food_production_by_puma$total_foreign_hispanic)
What’s that as a percent of all foreign workers in these industries?
sum(ipums_food_production_by_puma$total_foreign_hispanic) /
sum(ipums_food_production_by_puma$total_foreign) * 100
Which PUMAs have the highest number of immigrant foodworkers?
ipums_food_production_by_puma %>%
arrange(desc(total_foreign)) %>%
select(
state,
puma,
total_employment_selected_industries,
total_foreign,
total_foreign_hispanic
) %>%
head(23) # 2,341 PUMAs / 100 = 23.41
And how many immigrant workers are in these PUMAs?
ipums_food_production_by_puma %>%
arrange(desc(total_foreign)) %>%
select(puma,
total_employment_selected_industries,
total_foreign,
total_foreign_hispanic) %>%
head(23) %>%
ungroup() %>%
summarize(sum(total_foreign))
And how many of these foreign-born workers are Hispanic?
ipums_food_production_by_puma %>%
arrange(desc(total_foreign)) %>%
select(puma,
total_employment_selected_industries,
total_foreign,
total_foreign_hispanic) %>%
head(23) %>%
ungroup() %>%
summarize(sum(total_foreign_hispanic))
Which counties have the highest number of immigrant foodworkers?
ipums_food_production_by_county %>%
arrange(desc(total_foreign)) %>%
select(
state,
county,
total_employment_selected_industries,
total_foreign,
total_foreign_hispanic
) %>%
head(31) # 3,142 counties / 100 = 31.42
And how many immigrant workers are in these counties?
ipums_food_production_by_county %>%
arrange(desc(total_foreign)) %>%
select(
county,
total_employment_selected_industries,
total_foreign,
total_foreign_hispanic
) %>%
head(31) %>%
ungroup() %>%
summarize(sum(total_foreign))
And how many of these foreign-born workers are Hispanic?
ipums_food_production_by_county %>%
arrange(desc(total_foreign)) %>%
select(
county,
total_employment_selected_industries,
total_foreign,
total_foreign_hispanic
) %>%
head(31) %>%
ungroup() %>%
summarize(sum(total_foreign_hispanic))
What is the distribution of foreign workers in these industries by state?
foodworkers_by_state <- ipums_food_production_by_puma %>%
group_by(state) %>%
summarize(
state_total_employment_selected_industries =
sum(total_employees),
state_total_foreign = sum(total_foreign),
state_pct_total_foreign = round(
sum(total_foreign) / sum(total_employees) * 100
),
2,
state_total_foreign_hispanic = sum(total_foreign_hispanic),
state_pct_total_foreign_hispanic = round(
sum(total_foreign_hispanic) /
sum(total_employees) * 100
),
2
) %>%
mutate(
rank_total_employment = dense_rank(desc(
state_total_employment_selected_industries
)),
rank_total_foreign = dense_rank(desc(state_total_foreign)),
rank_total_foreign_hispanic = dense_rank(desc(state_total_foreign_hispanic))
) %>%
select(
state,
state_total_employment_selected_industries,
state_total_foreign,
state_pct_total_foreign,
state_total_foreign_hispanic,
state_pct_total_foreign_hispanic,
rank_total_employment,
rank_total_foreign,
rank_total_foreign_hispanic
) %>%
arrange(desc(state_total_employment_selected_industries))
foodworkers_by_state
What proportion of total foodworker employment do the top 10 states account for?
foodworkers_by_state %>%
arrange(desc(state_total_employment_selected_industries)) %>%
head(10) %>%
summarize(sum(state_total_employment_selected_industries))
What is the distribution of foreign workers in these industries by state?
foodworkers_by_state %>%
summarize(sum(state_total_employment_selected_industries))
Where do the “Red Zone” states stand?
red_zone <-
data.frame(
"state" = c(
"Alabama/AL",
"Arizona/AZ",
"Arkansas/AR",
"California/CA",
"Florida/FL",
"Georgia/GA",
"Idaho/ID",
"Iowa/IA",
"Kansas/KS",
"Louisiana/LA",
"Mississippi/MS",
"Missouri/MO",
"Nevada/NV",
"North Carolina/NC",
"North Dakota/ND",
"Oklahoma/OK",
"South Carolina/SC",
"Tennessee/TN",
"Texas/TX",
"Utah/UT",
"Wisconsin/WI"
),
"red_zone" = TRUE
)
red_zone
Join with the red zone states data frame
foodworkers_by_state <- foodworkers_by_state %>%
left_join(red_zone, by = "state")
Where do the Red Zone states stand?
foodworkers_by_state %>%
filter(red_zone == TRUE)
Export the states
write_csv(foodworkers_by_state,
"data/exported/foodworkers_by_state.csv")
LS0tCnRpdGxlOiAiY292aWQtaW1taWdyYW50LWZvb2R3b3JrZXJzIgphdXRob3I6ICJKb2UgWWVyYXJkaSIKZGF0ZTogIjUvNy8yMDIwIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGfQojIFdlIGRvbid0IHdhbnQgdG8gc2VlIGFueSB3YXJuaW5ncyBmcm9tIG91ciBjb2RlCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRikKCiMgV2UgZG9uJ3Qgd2FudCB0byBzZWUgYW55IG1lc3NhZ2VzCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRikKCiMgU2V0IGtleSBmaWxlIGZvciB0aGUgQ2Vuc3VzIEJ1cmVhdSBBUEkga2V5CmtleV9maWxlIDwtICJrZXlfZmlsZS50eHQiCmBgYAoKYGBge3IsIGluY2x1ZGUgPSBGfQpsaWJyYXJ5KGlwdW1zcikKbGlicmFyeShsYWJlbGxlZCkKbGlicmFyeShwdXJycikKbGlicmFyeShyZ2RhbCkKbGlicmFyeShzZikKbGlicmFyeSh0aWR5Y2Vuc3VzKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0aWdyaXMpCmBgYAoKIyBJbXBvcnQgYW5kIGZvcm1hdCBkYXRhCgojIyBJbXBvcnQgSVBVTVMKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIElQVU1TICgyMDE0LTE4IEFDUzsgcG9wdWxhdGlvbiA9IDE2IGFuZCBvbGRlcjsgZW1wbG95ZWQgLSBhdCB3b3JrLAojIGVtcGxveWVkIC0gbm90IGF0IHdvcmspCmlwdW1zIDwtIHJlYWQudGFibGUoImRhdGEvdXNhXzAwMDE1LmRhdCIpCmRkaSA8LSByZWFkX2lwdW1zX2RkaSgiZGF0YS91c2FfMDAwMTUueG1sIikKaXB1bXMgPC0gcmVhZF9pcHVtc19taWNybyhkZGkpICU+JQogIG11dGF0ZSgKICAgIHN0YXRlX2NvZGUgPSBhc19mYWN0b3IoVVMyMDE4Q19TVCwgbGV2ZWxzID0gInZhbHVlcyIpLAogICAgc3RhdGUgPSBhc19mYWN0b3IoVVMyMDE4Q19TVCwgbGV2ZWxzID0gImxhYmVscyIpLAogICAgcHVtYV9jb2RlID0gcGFzdGUwKHN0YXRlX2NvZGUsIGFzX2ZhY3RvcihVUzIwMThDX1BVTUEpKSwKICAgIGluZHVzdHJ5X2NvZGUgPSBhc19mYWN0b3IoVVMyMDE4Q19JTkRQLCBsZXZlbHMgPSAidmFsdWVzIiksCiAgICBpbmR1c3RyeSA9IGFzX2ZhY3RvcihVUzIwMThDX0lORFAsIGxldmVscyA9ICJsYWJlbHMiKSwKICAgIG9jY3VwYXRpb25fY29kZSA9ICBhc19mYWN0b3IoVVMyMDE4Q19PQ0NQLCBsZXZlbHMgPSAidmFsdWVzIiksCiAgICBvY2N1cGF0aW9uID0gYXNfZmFjdG9yKFVTMjAxOENfT0NDUCwgbGV2ZWxzID0gImxhYmVscyIpLAogICAgY2l0aXplbnNoaXBfY29kZSA9IGFzX2ZhY3RvcihDSVRJWkVOLCBsZXZlbHMgPSAidmFsdWVzIiksCiAgICBjaXRpemVuc2hpcCA9IGFzX2ZhY3RvcihDSVRJWkVOLCBsZXZlbHMgPSAibGFiZWxzIiksCiAgICBldGhuaWNpdHlfY29kZSA9IGFzX2ZhY3RvcihISVNQQU4sIGxldmVscyA9ICJ2YWx1ZXMiKSwKICAgIGV0aG5pY2l0eSA9IGFzX2ZhY3RvcihISVNQQU4sIGxldmVscyA9ICJsYWJlbHMiKQogICkgJT4lCiAgc2VsZWN0KDE2OjI2LCA1KQoKaXB1bXMKYGBgCgojIyBQVU1BIHNoYXBlZmlsZXMKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpwdW1hcyA8LSByZWFkT0dSKCJkYXRhL2lwdW1zX3B1bWFfMjAxMC9pcHVtc19wdW1hXzIwMTAuc2hwIikgJT4lCiAgIyBDb252ZXJ0IHNoYXBlZmlsZSB0byBzZiBvYmplY3QKICBzdF9hc19zZihjcnMgPSA1MDcwLCByZW1vdmUgPSBGKSAlPiUKICBzZWxlY3QocHVtYV9jb2RlID0gR0VPSUQsIHB1bWEgPSBOYW1lLCBnZW9tZXRyeSkKYGBgCgojIyBDb3VudHkgc2hhcGVmaWxlcwoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmNvdW50aWVzIDwtCiAgcmVhZE9HUigiZGF0YS90bF8yMDE5X3VzX2NvdW50eS90bF8yMDE5X3VzX2NvdW50eS5zaHAiKSAlPiUKICAjIENvbnZlcnQgc2hhcGVmaWxlIHRvIHNmIG9iamVjdAogIHN0X2FzX3NmKGNycyA9IDUwNzAsIHJlbW92ZSA9IEYpICU+JQogIHNlbGVjdChjb3VudHlfY29kZSA9IEdFT0lELCBjb3VudHkgPSBOQU1FTFNBRCwgZ2VvbWV0cnkpCmBgYAoKIyMgQ09WSUQgY291bnR5IGNhc2VzIGFuZCBkZWF0aHMKCmBgYHtyfQpjb3ZpZCA8LSByZWFkX2NzdigiZGF0YS91cy1jb3VudGllcy5jc3YiLAogICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKC5kZWZhdWx0ID0gIj8iLCBkYXRlID0gIkQiKSkgJT4lCiAgcmVuYW1lKGNvdW50eV9jb2RlID0gZmlwcykgJT4lCiAgIyBGaWx0ZXIgdG8gdGhlIGxhdGVzdCBkYXRhIGZvciBlYWNoIGNvdW50eQogIGdyb3VwX2J5KGNvdW50eV9jb2RlKSAlPiUKICBzbGljZSh3aGljaC5tYXgoZGF0ZSkpCgpjb3ZpZApgYGAKCiMjIENvdW50eSBwb3B1bGF0aW9ucwoKIyMjIFJlYWQtaW4gQ2Vuc3VzIEFQSSBrZXkKCmBgYHtyfQpjZW5zdXNfa2V5IDwtIChyZWFkTGluZXMoa2V5X2ZpbGUpWzFdKQpgYGAKCiMjIyBDcmVhdGUgbGlzdCBvZiBhbGwgVVMgc3RhdGVzIHRvIGl0ZXJhdGUgdGhyb3VnaCBpbiB0aGUgQVBJIGNhbGxzCgpgYGB7cn0KdXMgPC0gdW5pcXVlKGZpcHNfY29kZXMkc3RhdGUpWzE6NTFdCgp1cwpgYGAKCiMjIyBEb3dubG9hZCBwb3B1bGF0aW9uIGRhdGEgZnJvbSB0aGUgMjAxNC0yMDE4IEFDUwoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnBvcHVsYXRpb24gPC0gbWFwX2Rmcih1cywgZnVuY3Rpb24oeCkgewogIGdldF9hY3MoCiAgICBnZW9ncmFwaHkgPSAiY291bnR5IiwKICAgIHZhcmlhYmxlcyA9ICJCMDEwMDFfMDAxIiwKICAgIHN0YXRlID0geCwKICAgIGtleSA9IGNlbnN1c19rZXkKICApCn0pICU+JQogIG11dGF0ZShpbmNvbWVfcXVhcnRpbGUgPSBudGlsZShlc3RpbWF0ZSwgNCkpICU+JQogIHNlbGVjdChjb3VudHlfY29kZSA9IEdFT0lELAogICAgICAgICBjb3VudHkgPSBOQU1FLAogICAgICAgICBwb3B1bGF0aW9uID0gZXN0aW1hdGUpCgpwb3B1bGF0aW9uCmBgYAoKIyMgUFVNQS10by1jb3VudHkgY3Jvc3N3YWxrCgpgYGB7cn0KY291bnR5X3RvX3B1bWFfY3Jvc3N3YWxrIDwtIHJlYWRfY3N2KCJkYXRhL2dlb2NvcnIyMDE4LmNzdiIsIHNraXAgPSAxKSAlPiUKICBtdXRhdGUocHVtYV9jb2RlID0gcGFzdGUwKGBTdGF0ZSBjb2RlYCwgYFBVTUEgKDIwMTIpYCkpICU+JQogIHNlbGVjdCgKICAgIHB1bWFfY29kZSwKICAgIGNvdW50eV9jb2RlID0gYENvdW50eSBjb2RlICgyMDE0KWAsCiAgICBzdGF0ZSA9IGBTdGF0ZSBhYmJyZXZpYXRpb25gLAogICAgY291bnR5ID0gYDIwMTQgY291bnR5IG5hbWVgLAogICAgcHVtYSA9IGBQVU1BMTIgbmFtZWAsCiAgICBhbGxvY2F0aW9uX2ZhY3RvciA9IGBwdW1hMTIgdG8gY291bnR5MTQgYWxsb2NhdGlvbiBmYWN0b3JgCiAgKQoKY291bnR5X3RvX3B1bWFfY3Jvc3N3YWxrCmBgYAoKIyMgSm9pbiB0aGUgQ09WSUQsIHBvcHVsYXRpb24gYW5kIGNyb3Nzd2FsayBkYXRhIGZyYW1lcwoKYGBge3J9CmNyb3Nzd2FsayA8LSBsaXN0KGNvdmlkLCBwb3B1bGF0aW9uLCBjb3VudHlfdG9fcHVtYV9jcm9zc3dhbGspICU+JQogIHJlZHVjZShmdWxsX2pvaW4sIGJ5ID0gImNvdW50eV9jb2RlIikgJT4lCiAgbXV0YXRlKAogICAgcHVtYSA9IHBhc3RlKHB1bWEsIHN0YXRlLngsIHNlcCA9ICIsICIpLAogICAgY2FzZXNfcGVyXzEwMGsgPSByb3VuZChjYXNlcyAvIHBvcHVsYXRpb24gKiAxMDAwMDAsIGRpZ2l0cyA9IDApLAogICAgZGVhdGhzX3Blcl8xMDBrID0gcm91bmQoZGVhdGhzIC8gcG9wdWxhdGlvbiAqIDEwMDAwMCwgZGlnaXRzID0gMCkKICApICU+JQogIHNlbGVjdCgKICAgIDEsCiAgICBzdGF0ZSA9IHN0YXRlLngsCiAgICBjb3VudHlfY29kZSwKICAgIGNvdW50eSA9IGNvdW50eS55LAogICAgcHVtYV9jb2RlLAogICAgcHVtYSwKICAgIHBvcHVsYXRpb24sCiAgICBjYXNlcywKICAgIGRlYXRocywKICAgIGNhc2VzX3Blcl8xMDBrLAogICAgZGVhdGhzX3Blcl8xMDBrLAogICAgYWxsb2NhdGlvbl9mYWN0b3IKICApCgpjcm9zc3dhbGsKYGBgCgojIyBGaWx0ZXIgdG8gdGhlIGZvb2QgcHJvZHVjdGlvbiBpbmR1c3RyaWVzIHdlJ3JlIGludGVyZXN0ZWQgaW4KCmBgYHtyfQpmb29kX3Byb2R1Y3Rpb25faW5kdXN0cmllcyA8LQogIGxpc3QoIjAxNzAiLCAjIENyb3AgcHJvZHVjdGlvbgogICAgICAgIjAxODAiLCAjIEFuaW1hbCBwcm9kdWN0aW9uIGFuZCBhcXVhY3VsdHVyZQogICAgICAgIjAyOTAiLCAjIFN1cHBvcnQgYWN0aXZpdGllcyBmb3IgYWdyaWN1bHR1cmUgYW5kIGZvcmVzdHJ5CiAgICAgICAiMTA3MCIsICMgQW5pbWFsIGZvb2QsIGdyYWluIGFuZCBvaWxzZWVkIG1pbGxpbmcKICAgICAgICIxMDgwIiwgIyBTdWdhciBhbmQgY29uZmVjdGlvbmVyeSBwcm9kdWN0cwogICAgICAgIjEwOTAiLCAjIEZydWl0IGFuZCB2ZWdldGFibGUgcHJlc2VydmluZyBhbmQgc3BlY2lhbHR5IGZvb2QgbWFudWZhY3R1cmluZwogICAgICAgIjExNzAiLCAjIERhaXJ5IHByb2R1Y3QgbWFudWZhY3R1cmluZwogICAgICAgIjExODAiLCAjIEFuaW1hbCBzbGF1Z2h0ZXJpbmcgYW5kIHByb2Nlc3NpbmcKICAgICAgICIxMjcwIiwgIyBCYWtlcmllcyBhbmQgdG9ydGlsbGEgbWFudWZhY3R1cmluZywgZXhjZXB0IHJldGFpbCBiYWtlcmllcwogICAgICAgIjEyODAiLCAjIFNlYWZvb2QgYW5kIG90aGVyIG1pc2NlbGxhbmVvdXMgZm9vZHM7IG4uZS5jLgogICAgICAgIjEyOTAiKSAjIE5vdCBzcGVjaWZpZWQgZm9vZCBpbmR1c3RyaWVzCgppcHVtc19mb29kX3Byb2R1Y3Rpb24gPC0gaXB1bXMgJT4lCiAgZmlsdGVyKGluZHVzdHJ5X2NvZGUgJWluJSBmb29kX3Byb2R1Y3Rpb25faW5kdXN0cmllcykKYGBgCgojIyBDYWxjdWxhdGUgZW1wbG95bWVudCBieSBpbmR1c3RyeS1vY2N1cGF0aW9uIGdyb3VwaW5nCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2VtcGxveW1lbnRfYnlfaW5kX29jYyA8LQogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbiAlPiUKICBncm91cF9ieShpbmR1c3RyeSwgb2NjdXBhdGlvbikgJT4lCiAgc3VtbWFyaXplKG51bV9lbXBsb3llZXMgPSBzdW0oUEVSV1QpKSAlPiUKICBwaXZvdF93aWRlcigKICAgIGlkX2NvbHMgPSBjKGluZHVzdHJ5LCBvY2N1cGF0aW9uKSwKICAgIHZhbHVlc19mcm9tID0gbnVtX2VtcGxveWVlcywKICAgIG5hbWVzX3ByZWZpeCA9ICJudW1fZW1wbG95ZWVzIgogICkgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgMCkgJT4lCiAgIyBFeGNsdWRlIGZyb20gb3VyIGFuYWx5c2lzIGluZC1vY2MgZ3JvdXBpbmdzCiAgIyB3aXRoIGZld2VyIHRoYW4gMiw1MDAgZW1wbG95ZWVzIG5hdGlvbmFsbHkKICBmaWx0ZXIobnVtX2VtcGxveWVlcyA+PSAyNTAwKQpgYGAKCiMjIEV4cG9ydCB0aGUgZGF0YQoKYGBge3J9CndyaXRlX2NzdigKICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fZW1wbG95bWVudF9ieV9pbmRfb2NjLAogICJkYXRhL2V4cG9ydGVkL2lwdW1zX2Zvb2RfcHJvZHVjdGlvbl9lbXBsb3ltZW50X2J5X2luZF9vY2MuY3N2IgopCmBgYAoKIyMgRmlsdGVyIHRoZSBpbmR1c3RyeS1vY2N1cGF0aW9uIHBhaXJzCgojIyMgSW1wb3J0IGRhdGEgZnJhbWUgb2YgZm9vZCBwcm9kdWN0aW9uIGluZHVzdHJ5LW9jY3VwYXRpb24gcGFpcnMKCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fZW1wbG95bWVudF9ieV9pbmRfb2NjIDwtCiAgcmVhZF9jc3YoImRhdGEvaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3RvdGFsX2VtcGxveW1lbnRfYnlfaW5kX29jYy5jc3YiKQpgYGAKCiMjIyBKb2luIHRoZSBpbmR1c3RyeS1vY2N1cGF0aW9uIHBhaXJzIHRvIHRoZSBpcHVtcyBkYXRhIGFuZCBmaWx0ZXIgdG8ganVzdCB0aGUgaW5kdXN0cnktb2NjdXBhdGlvbiBwYWlycyB3ZSB3YW50CgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uICU+JQogIGlubmVyX2pvaW4oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2VtcGxveW1lbnRfYnlfaW5kX29jYywKICAgICAgICAgICAgIGJ5ID0gYygiaW5kdXN0cnkiLCAib2NjdXBhdGlvbiIpKSAlPiUKICBmaWx0ZXIoZXhjbHVkZSA9PSBGQUxTRSkgJT4lCiAgc2VsZWN0KC1udW1fZW1wbG95ZWVzLCAtZXhjbHVkZSkKCmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9ucwpgYGAKCiMjIEFuZCBqb2luIHdpdGggdGhlIHB1bWFzIGRhdGEgZnJhbWUgdG8gZ2V0IHRoZSBQVU1BIG5hbWVzCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zICU+JQogIGxlZnRfam9pbihwdW1hcywgYnkgPSAicHVtYV9jb2RlIikgJT4lCiAgbXV0YXRlKHB1bWEgPSBwYXN0ZShwdW1hLCBzdGF0ZSwgc2VwID0gIiwgIikpICU+JQogIHNlbGVjdCgxOjMsCiAgICAgICAgIDEzLAogICAgICAgICA0OjEyKQoKaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zCmBgYAoKYGBge3J9CmNpdGl6ZW5zaGlwX2xvb2t1cCA9IHRpYmJsZSgKICBjaXRpemVuc2hpcF9jb2RlID0gZmFjdG9yKGMoCiAgICAwLCAxLCAyLCAzLCA0LCA1CiAgKSksCiAgY2l0aXplbnNoaXAgPSBjKAogICAgIm5hdGl2ZV9jaXRpemVuIiwgIyBuL2EKICAgICJuYXRpdmVfY2l0aXplbiIsICMgYm9ybl9hYnJvYWRfY2l0aXplbgogICAgIm5hdHVyYWxpemVkX2NpdGl6ZW4iLCAjIG5hdHVyYWxpemVkX2NpdGl6ZW4KICAgICJub25fY2l0aXplbiIsICMgbm9uX2NpdGl6ZW4KICAgICJub25fY2l0aXplbl93aXRoX3BhcGVycyIsICMgbm9uX2NpdGl6ZW5fd2l0aF9wYXBlcnMKICAgICJmb3JlaWduX2Jvcm5fc3RhdHVzX3Vua25vd24iCiAgKQopCgpldGhuaWNpdHlfbG9va3VwID0gdGliYmxlKAogIGV0aG5pY2l0eV9jb2RlID0gZmFjdG9yKGMoCiAgICAwLCAxLCAyLCAzLCA0LCA5CiAgKSksCiAgZXRobmljaXR5ID0gYygKICAgICJub25faGlzcGFuaWMiLAogICAgImhpc3BhbmljIiwgIyBtZXhpY2FuCiAgICAiaGlzcGFuaWMiLCAjIHB1ZXJ0b19yaWNhbgogICAgImhpc3BhbmljIiwgIyBjdWJhbgogICAgImhpc3BhbmljIiwgIyBvdGhlcgogICAgIm5vdF9yZXBvcnRlZCIKICApCikKCmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9uc19tYXBwZWQgPC0KICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fc2VsZWN0ZWRfb2NjdXBhdGlvbnMgJT4lCiAgc2VsZWN0KC1ldGhuaWNpdHksLWNpdGl6ZW5zaGlwKSAlPiUKICBsZWZ0X2pvaW4oZXRobmljaXR5X2xvb2t1cCwgYnk9ImV0aG5pY2l0eV9jb2RlIikgJT4lCiAgbGVmdF9qb2luKGNpdGl6ZW5zaGlwX2xvb2t1cCwgYnk9ImNpdGl6ZW5zaGlwX2NvZGUiKQpgYGAKCmBgYHtyfQpwY3QgPC0gZnVuY3Rpb24gKHBhcnQsd2hvbGUpIHsKICByb3VuZChwYXJ0IC8gd2hvbGUgKiAxMDAsIGRpZ2l0cyA9IDApCn0KYGBgCgoKYGBge3J9CmNhbGNfcGVyY2VudHMgPC0gZnVuY3Rpb24gKHJvd3MpIHsKICByb3dzICU+JQogIG11dGF0ZSgKICAgIHRvdGFsX25hdGl2ZV9jaXRpemVuID0gKAogICAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgKwogICAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW4gPSAoCiAgICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsKICAgICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX25vbl9jaXRpemVuID0gKAogICAgICB0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgKwogICAgICB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljID0gKAogICAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX25vbl9oaXNwYW5pYyArCiAgICAgIHRvdGFsX25vbl9jaXRpemVuX25vbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMgPSAoCiAgICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMgKwogICAgICB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2ZvcmVpZ24gPSAoCiAgICAgIHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljICsKICAgICAgdG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICAgKSwKICAgIHRvdGFsX2VtcGxveWVlcyA9ICgKICAgICAgICB0b3RhbF9uYXRpdmVfY2l0aXplbiArCiAgICAgICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbiArCiAgICAgICAgdG90YWxfbm9uX2NpdGl6ZW4KICAgICksCiAgICBwY3RfbmF0aXZlX2NpdGl6ZW5fbm9uX2hpc3BhbmljID0gCiAgICAgIHBjdCh0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMsIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3RfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMsIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3RfdG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMsIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3RfdG90YWxfZm9yZWlnbl9oaXNwYW5pYyA9CiAgICAgIHBjdCh0b3RhbF9mb3JlaWduX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljID0KICAgICAgcGN0KHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYywgdG90YWxfZW1wbG95ZWVzKSwKICAgIHBjdF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgPQogICAgICBwY3QodG90YWxfbm9uX2NpdGl6ZW5fbm9uX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25vbl9jaXRpemVuX2hpc3BhbmljID0KICAgICAgcGN0KHRvdGFsX25vbl9jaXRpemVuX2hpc3BhbmljLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X25hdGl2ZV9jaXRpemVuID0KICAgICAgcGN0KHRvdGFsX25hdGl2ZV9jaXRpemVuLCB0b3RhbF9lbXBsb3llZXMpLAogICAgcGN0X3RvdGFsX2ZvcmVpZ24gPQogICAgICBwY3QodG90YWxfZm9yZWlnbiwgdG90YWxfZW1wbG95ZWVzKSwKICAgIHBjdF9uYXR1cmFsaXplZF9jaXRpemVuID0KICAgICAgcGN0KHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW4sIHRvdGFsX2VtcGxveWVlcyksCiAgICBwY3Rfbm9uX2NpdGl6ZW4gPQogICAgICBwY3QodG90YWxfbm9uX2NpdGl6ZW4sIHRvdGFsX2VtcGxveWVlcykKICApCn0KYGBgCgoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9uc19tYXBwZWQKYGBgCgojIyBDYWxjdWxhdGUgdGhlIG5hdGlvbmFsLWxldmVsIGNpdGl6ZW5zaGlwIGFuZCBldGhuaWNpdHkgZGF0YSBmb3IgdGhlc2UgaW5kdXN0cnktb2NjdXBhdGlvbiBwYWlycwoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9pbmR1c3RyeV9vY2N1cGF0aW9uIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zX21hcHBlZCAlPiUKICBncm91cF9ieShpbmR1c3RyeV9jb2RlLAogICAgICAgICAgIGluZHVzdHJ5LAogICAgICAgICAgIG9jY3VwYXRpb25fY29kZSwKICAgICAgICAgICBvY2N1cGF0aW9uLAogICAgICAgICAgIGNpdGl6ZW5zaGlwLAogICAgICAgICAgIGV0aG5pY2l0eSkgJT4lCiAgc3VtbWFyaXplKG51bV9lbXBsb3llZXMgPSBzdW0oUEVSV1QpKSAlPiUKICBwaXZvdF93aWRlcigKICAgIGlkX2NvbHMgPSBjKGluZHVzdHJ5X2NvZGUsIGluZHVzdHJ5LCBvY2N1cGF0aW9uX2NvZGUsIG9jY3VwYXRpb24pLAogICAgbmFtZXNfZnJvbSA9IGMoY2l0aXplbnNoaXAsIGV0aG5pY2l0eSksCiAgICB2YWx1ZXNfZnJvbSA9IG51bV9lbXBsb3llZXMsCiAgICBuYW1lc19wcmVmaXggPSAidG90YWxfIgogICkgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgMCkgJT4lCiAgY2FsY19wZXJjZW50cygpCmBgYAoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9pbmR1c3RyeV9vY2N1cGF0aW9uCmBgYAoKIyMjIEV4cG9ydCB0aGUgZGF0YQoKYGBge3J9CndyaXRlX2NzdigKICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfaW5kdXN0cnlfb2NjdXBhdGlvbiwKICAiZGF0YS9leHBvcnRlZC9pcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfaW5kdXN0cnlfb2NjdXBhdGlvbi5jc3YiCikKYGBgCgojIyMgR3JvdXAgdGhlIGRhdGEgYnkgUFVNQQoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX3NlbGVjdGVkX29jY3VwYXRpb25zX21hcHBlZCAlPiUKICBncm91cF9ieShzdGF0ZV9jb2RlLAogICAgICAgICAgIHN0YXRlLAogICAgICAgICAgIHB1bWFfY29kZSwKICAgICAgICAgICBwdW1hLAogICAgICAgICAgIGNpdGl6ZW5zaGlwLAogICAgICAgICAgIGV0aG5pY2l0eSkgJT4lCiAgc3VtbWFyaXplKG51bV9lbXBsb3llZXMgPSBzdW0oUEVSV1QsIG5hLnJtID0gVFJVRSkpICU+JQogIHBpdm90X3dpZGVyKAogICAgaWRfY29scyA9IGMoc3RhdGVfY29kZSwgc3RhdGUsIHB1bWFfY29kZSwgcHVtYSksCiAgICBuYW1lc19mcm9tID0gYyhjaXRpemVuc2hpcCwgZXRobmljaXR5KSwKICAgIHZhbHVlc19mcm9tID0gbnVtX2VtcGxveWVlcywKICAgIG5hbWVzX3ByZWZpeCA9ICJ0b3RhbF8iCiAgKSAlPiUKICByZXBsYWNlKGlzLm5hKC4pLCAwKSAlPiUKICBjYWxjX3BlcmNlbnRzKCkKYGBgCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEgJT4lIHNlbGVjdChwdW1hX2NvZGUsdG90YWxfZm9yZWlnbikKYGBgCgojIyMgRXhwb3J0IHRoZSBkYXRhCgpgYGB7cn0Kd3JpdGVfY3N2KAogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hLAogICJkYXRhL2V4cG9ydGVkL2lwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hLmNzdiIKKQpgYGAKCiMjIEdyb3VwIHRoZSBkYXRhIGJ5IFBVTUEgYW5kIGluZHVzdHJ5IGFuZCBvY2N1cGF0aW9uCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jYyA8LQogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9zZWxlY3RlZF9vY2N1cGF0aW9uc19tYXBwZWQgJT4lCiAgZ3JvdXBfYnkoCiAgICBzdGF0ZV9jb2RlLAogICAgc3RhdGUsCiAgICBwdW1hX2NvZGUsCiAgICBwdW1hLAogICAgaW5kdXN0cnlfY29kZSwKICAgIGluZHVzdHJ5LAogICAgb2NjdXBhdGlvbl9jb2RlLAogICAgb2NjdXBhdGlvbiwKICAgIGNpdGl6ZW5zaGlwLAogICAgZXRobmljaXR5CiAgKSAlPiUKICBzdW1tYXJpemUobnVtX2VtcGxveWVlcyA9IHN1bShQRVJXVCkpICU+JQogIHBpdm90X3dpZGVyKAogICAgaWRfY29scyA9IGMoCiAgICAgIHN0YXRlX2NvZGUsCiAgICAgIHN0YXRlLAogICAgICBwdW1hX2NvZGUsCiAgICAgIHB1bWEsCiAgICAgIGluZHVzdHJ5X2NvZGUsCiAgICAgIGluZHVzdHJ5LAogICAgICBvY2N1cGF0aW9uX2NvZGUsCiAgICAgIG9jY3VwYXRpb24KICAgICksCiAgICBuYW1lc19mcm9tID0gYyhjaXRpemVuc2hpcCwgZXRobmljaXR5KSwKICAgIHZhbHVlc19mcm9tID0gbnVtX2VtcGxveWVlcywKICAgIG5hbWVzX3ByZWZpeCA9ICJ0b3RhbF8iCiAgKSAlPiUKICByZXBsYWNlKGlzLm5hKC4pLCAwKSAlPiUKICBjYWxjX3BlcmNlbnRzKCkKYGBgCgojIyMgRXhwb3J0IHRoZSBkYXRhCgpgYGB7cn0Kd3JpdGVfY3N2KAogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2luZF9vY2MsCiAgImRhdGEvZXhwb3J0ZWQvaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jYy5jc3YiCikKYGBgCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEKYGBgCgojIyBKb2luIHRoZSBlbXBsb3ltZW50IGRhdGEgdG8gdGhlIGNyb3Nzd2FsayBkYXRhIGZyYW1lCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEKYGBgCgpgYGB7ciBjcm9zc3dhbGsgdGhlIGVtcGxveW1lbnQgZGF0YSBmcm9tIFBVTUFzIHRvIGNvdW50aWVzfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkgPC0KICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSAlPiUKICBsZWZ0X2pvaW4oY3Jvc3N3YWxrLCBieSA9ICJwdW1hX2NvZGUiKSAlPiUKICBtdXRhdGUoCiAgICB0b3RhbF9lbXBsb3llZXMgPSByb3VuZCgKICAgICAgdG90YWxfZW1wbG95ZWVzICogYWxsb2NhdGlvbl9mYWN0b3IsCiAgICAgIGRpZ2l0cyA9IDAKICAgICksCiAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgKgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25hdGl2ZV9jaXRpemVuX2hpc3BhbmljICoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9mb3JlaWduX25vbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljICoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljID0gcm91bmQodG90YWxfZm9yZWlnbl9oaXNwYW5pYyAqCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX25vbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX25vbl9jaXRpemVuX25vbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25vbl9jaXRpemVuX25vbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYyA9IHJvdW5kKHRvdGFsX25vbl9jaXRpemVuX2hpc3BhbmljCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0aXZlX2NpdGl6ZW4gPSB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgKyB0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYywKICAgIHRvdGFsX2ZvcmVpZ24gPSB0b3RhbF9mb3JlaWduX25vbl9oaXNwYW5pYyArIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMsCiAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuID0gdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9ub25faGlzcGFuaWMgKwogICAgICB0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX2hpc3BhbmljLAogICAgdG90YWxfbm9uX2NpdGl6ZW4gPSB0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgKyB0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICkgJT4lCiAgc2VsZWN0KDEsCiAgICAgICAgIHN0YXRlID0gc3RhdGUueCwKICAgICAgICAgMywKICAgICAgICAgcHVtYSA9IHB1bWEueCwKICAgICAgICAgMzI6MzMsCiAgICAgICAgIDM1OjQwLAogICAgICAgICA1OjE3KQpgYGAKCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkKYGBgCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkgJT4lIGZpbHRlcihjb3VudHlfY29kZSA9PSAiMDYwNTMiKSAlPiUgc2VsZWN0KGFsbG9jYXRpb25fZmFjdG9yLCB0b3RhbF9lbXBsb3llZXMsIHRvdGFsX2ZvcmVpZ24sIHRvdGFsX25vbl9jaXRpemVuKQpgYGAKCiMjIyBKb2luIHRoZSBlbXBsb3ltZW50IGRhdGEgdG8gdGhlIGNyb3Nzd2FsayBkYXRhIGZyYW1lCmBgYHtyIGNyb3Nzd2FsayB0aGUgZW1wbG95bWVudCBkYXRhIGZyb20gUFVNQXMgYW5kIGluZC1vY2MgcGFpcnMgdG8gY291bnRpZXMgYW5kIGluZC1vY2MgcGFpcnN9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2luZF9vY2NfY3Jvc3N3YWxrZWRfdG9fY291bnR5IDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jYyAlPiUKICBsZWZ0X2pvaW4oY3Jvc3N3YWxrLCBieSA9ICJwdW1hX2NvZGUiKSAlPiUKICBtdXRhdGUoCiAgICB0b3RhbF9lbXBsb3llZXMgPSByb3VuZCgKICAgICAgdG90YWxfZW1wbG95ZWVzICogYWxsb2NhdGlvbl9mYWN0b3IsCiAgICAgIGRpZ2l0cyA9IDAKICAgICksCiAgICB0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXRpdmVfY2l0aXplbl9ub25faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXRpdmVfY2l0aXplbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX2ZvcmVpZ25fbm9uX2hpc3BhbmljID0gcm91bmQodG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljID0gcm91bmQodG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX25vbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9uYXR1cmFsaXplZF9jaXRpemVuX2hpc3BhbmljCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbGxvY2F0aW9uX2ZhY3RvciwgZGlnaXRzID0gMCksCiAgICB0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9ub25fY2l0aXplbl9ub25faGlzcGFuaWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogYWxsb2NhdGlvbl9mYWN0b3IsIGRpZ2l0cyA9IDApLAogICAgdG90YWxfbm9uX2NpdGl6ZW5faGlzcGFuaWMgPSByb3VuZCh0b3RhbF9ub25fY2l0aXplbl9oaXNwYW5pYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGFsbG9jYXRpb25fZmFjdG9yLCBkaWdpdHMgPSAwKSwKICAgIHRvdGFsX25hdGl2ZV9jaXRpemVuID0gdG90YWxfbmF0aXZlX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsgdG90YWxfbmF0aXZlX2NpdGl6ZW5faGlzcGFuaWMsCiAgICB0b3RhbF9mb3JlaWduID0gdG90YWxfZm9yZWlnbl9ub25faGlzcGFuaWMgKyB0b3RhbF9mb3JlaWduX2hpc3BhbmljLAogICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbiA9IHRvdGFsX25hdHVyYWxpemVkX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsKICAgICAgdG90YWxfbmF0dXJhbGl6ZWRfY2l0aXplbl9oaXNwYW5pYywKICAgIHRvdGFsX25vbl9jaXRpemVuID0gdG90YWxfbm9uX2NpdGl6ZW5fbm9uX2hpc3BhbmljICsgdG90YWxfbm9uX2NpdGl6ZW5faGlzcGFuaWMKICApICU+JQogIHNlbGVjdCgxLAogICAgICAgICBzdGF0ZSA9IHN0YXRlLngsCiAgICAgICAgIDMsCiAgICAgICAgIHB1bWEgPSBwdW1hLngsCiAgICAgICAgIDM2OjM3LAogICAgICAgICA1OjgsCiAgICAgICAgIDM5OjQ0LAogICAgICAgICA5OjIxKQpgYGAKCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYV9jcm9zc3dhbGtlZF90b19jb3VudHkKYGBgCgojIyBHcm91cCB0aGUgZGF0YSBieSBjb3VudHkKCmBgYHtyIGdyb3VwIHRoZSBkYXRhIGJ5IGNvdW50eX0KIyBUaGlzIHN0ZXAgaXMgcmVxdWlyZWQgdG8gZGVhbCB3aXRoIHNpdHVhdGlvbnMKIyB3aGVyZSBtdWx0aXBsZSBQVU1BcyBzcGxpdCBhIHNpbmdsZSBjb3VudHkKaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2NvdW50eSA8LQogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2Nyb3Nzd2Fsa2VkX3RvX2NvdW50eSAlPiUKICBncm91cF9ieShzdGF0ZV9jb2RlLCBzdGF0ZSwgY291bnR5X2NvZGUsIGNvdW50eSkgJT4lCiAgY2FsY19wZXJjZW50cygpCmBgYAoKIyMjIEV4cG9ydCB0aGUgZGF0YQoKYGBge3J9CndyaXRlX2NzdigKICBpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfY291bnR5LAogICJkYXRhL2V4cG9ydGVkL2lwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHkuY3N2IgopCmBgYAoKIyMgR3JvdXAgdGhlIGRhdGEgYnkgaW5kdXN0cnkgYW5kIG9jY3VwYXRpb24gYW5kIGNvdW50eQoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hX2luZF9vY2NfY3Jvc3N3YWxrZWRfdG9fY291bnR5CmBgYAoKYGBge3IgZ3JvdXAgdGhlIGRhdGEgYnkgaW5kdXN0cnkgYW5kIG9jY3VwYXRpb24gYW5kIGNvdW50eX0KIyBUaGlzIHN0ZXAgaXMgcmVxdWlyZWQgdG8gZGVhbCB3aXRoIHNpdHVhdGlvbnMKIyB3aGVyZSBtdWx0aXBsZSBQVU1BcyBzcGxpdCBhIHNpbmdsZSBjb3VudHkKaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2NvdW50eV9pbmRfb2NjIDwtCiAgaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWFfaW5kX29jY19jcm9zc3dhbGtlZF90b19jb3VudHkgJT4lCiAgZ3JvdXBfYnkoCiAgICBzdGF0ZV9jb2RlLAogICAgc3RhdGUsCiAgICBjb3VudHlfY29kZSwKICAgIGNvdW50eSwKICAgIGluZHVzdHJ5X2NvZGUsCiAgICBpbmR1c3RyeSwKICAgIG9jY3VwYXRpb25fY29kZSwKICAgIG9jY3VwYXRpb24KICApICU+JQogIGNhbGNfcGVyY2VudHMoKQpgYGAKCgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2NvdW50eV9pbmRfb2NjCmBgYAoKIyMjIEV4cG9ydCB0aGUgZGF0YQpgYGB7cn0Kd3JpdGVfY3N2KAogIGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHlfaW5kX29jYywKICAiZGF0YS9leHBvcnRlZC9pcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfY291bnR5X2luZF9vY2MuY3N2IgopCmBgYAoKIyBBbmFseXplIHRoZSBkYXRhCgojIyBXaGF0IGlzIHRoZSB0b3RhbCBudW1iZXIgb2Ygd29ya2VycyBlbXBsb3llZCBpbiB0aGVzZSBpbmR1c3RyaWVzPwoKYGBge3IgYW5hbHl6ZSBlbXBsb3ltZW50IGJ5IHRvdGFsIGZvcmVpZ259CnN1bShpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSR0b3RhbF9lbXBsb3llZXMpCmBgYAoKIyMgV2hhdCBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIGZvcmVpZ25lcnMgZW1wbG95ZWQgaW4gdGhlc2UgaW5kdXN0cmllcz8KCmBgYHtyfQpzdW0oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEkdG90YWxfZm9yZWlnbikKYGBgCgojIyBXaGF0J3MgdGhhdCBhcyBhIHBlcmNlbnQ/CgpgYGB7cn0Kc3VtKGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hJHRvdGFsX2ZvcmVpZ24pIC8KICBzdW0oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEkdG90YWxfZW1wbG95ZWVzKSAqIDEwMApgYGAKCiMjIEhvdyBtYW55IG9mIHRoZSBqb2JzIGhhdmUgYSBoaWdoZXIgcHJvcG9ydGlvbiBvZiBmb3JlaWduZXJzIGVtcGxveWVkIHRoYW4gdGhlIG5hdGlvbmFsIGF2ZXJhZ2Ugb2YgMTcuMSU/CgpgYGB7cn0KaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X2luZHVzdHJ5X29jY3VwYXRpb24gJT4lCiAgZmlsdGVyKHBjdF90b3RhbF9mb3JlaWduID4gMTcuMSkgJT4lCiAgc2VsZWN0KAogICAgaW5kdXN0cnksCiAgICBvY2N1cGF0aW9uLAogICAgdG90YWxfZW1wbG95ZWVzLAogICAgcGN0X3RvdGFsX2ZvcmVpZ24sCiAgICBwY3RfdG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2VtcGxveWVlcykpCmBgYAoKIyMgV2hhdCBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIEhpc3BhbmljIGZvcmVpZ25lcnMgZW1wbG95ZWQgaW4gdGhlc2UgaW5kdXN0cmllcz8KCmBgYHtyIGFuYWx5emUgZW1wbG95bWVudCBieSBmb3JlaWduIGFuZCBIaXNwYW5pY30Kc3VtKGlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hJHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpCmBgYAoKIyMgV2hhdCdzIHRoYXQgYXMgYSBwZXJjZW50IG9mIGFsbCBmb3JlaWduIHdvcmtlcnMgaW4gdGhlc2UgaW5kdXN0cmllcz8KCmBgYHtyfQpzdW0oaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEkdG90YWxfZm9yZWlnbl9oaXNwYW5pYykgLwogIHN1bShpcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSR0b3RhbF9mb3JlaWduKSAqIDEwMApgYGAKCiMjIFdoaWNoIFBVTUFzIGhhdmUgdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIGltbWlncmFudCBmb29kd29ya2Vycz8KCmBgYHtyIGFuYWx5emUgZW1wbG95bWVudCBieSBwdW1hfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSAlPiUKICBhcnJhbmdlKGRlc2ModG90YWxfZm9yZWlnbikpICU+JQogIHNlbGVjdCgKICAgIHN0YXRlLAogICAgcHVtYSwKICAgIHRvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcywKICAgIHRvdGFsX2ZvcmVpZ24sCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljCiAgKSAlPiUKICBoZWFkKDIzKSAjIDIsMzQxIFBVTUFzIC8gMTAwID0gMjMuNDEKYGBgCgojIyBBbmQgaG93IG1hbnkgaW1taWdyYW50IHdvcmtlcnMgYXJlIGluIHRoZXNlIFBVTUFzPwoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9wdW1hICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9mb3JlaWduKSkgJT4lCiAgc2VsZWN0KHB1bWEsCiAgICAgICAgIHRvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcywKICAgICAgICAgdG90YWxfZm9yZWlnbiwKICAgICAgICAgdG90YWxfZm9yZWlnbl9oaXNwYW5pYykgJT4lCiAgaGVhZCgyMykgJT4lCiAgdW5ncm91cCgpICU+JQogIHN1bW1hcml6ZShzdW0odG90YWxfZm9yZWlnbikpCmBgYAoKIyMgQW5kIGhvdyBtYW55IG9mIHRoZXNlIGZvcmVpZ24tYm9ybiB3b3JrZXJzIGFyZSBIaXNwYW5pYz8KCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfcHVtYSAlPiUKICBhcnJhbmdlKGRlc2ModG90YWxfZm9yZWlnbikpICU+JQogIHNlbGVjdChwdW1hLAogICAgICAgICB0b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMsCiAgICAgICAgIHRvdGFsX2ZvcmVpZ24sCiAgICAgICAgIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpICU+JQogIGhlYWQoMjMpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzdW1tYXJpemUoc3VtKHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpKQpgYGAKCiMjIFdoaWNoIGNvdW50aWVzIGhhdmUgdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIGltbWlncmFudCBmb29kd29ya2Vycz8KCmBgYHtyIGFuYWx5emUgZW1wbG95bWVudCBieSBjb3VudHl9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2ZvcmVpZ24pKSAlPiUKICBzZWxlY3QoCiAgICBzdGF0ZSwKICAgIGNvdW50eSwKICAgIHRvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcywKICAgIHRvdGFsX2ZvcmVpZ24sCiAgICB0b3RhbF9mb3JlaWduX2hpc3BhbmljCiAgKSAlPiUKICBoZWFkKDMxKSAjIDMsMTQyIGNvdW50aWVzIC8gMTAwID0gMzEuNDIKYGBgCgojIyBBbmQgaG93IG1hbnkgaW1taWdyYW50IHdvcmtlcnMgYXJlIGluIHRoZXNlIGNvdW50aWVzPwoKYGBge3J9CmlwdW1zX2Zvb2RfcHJvZHVjdGlvbl9ieV9jb3VudHkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2ZvcmVpZ24pKSAlPiUKICBzZWxlY3QoCiAgICBjb3VudHksCiAgICB0b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMsCiAgICB0b3RhbF9mb3JlaWduLAogICAgdG90YWxfZm9yZWlnbl9oaXNwYW5pYwogICkgJT4lCiAgaGVhZCgzMSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHN1bW1hcml6ZShzdW0odG90YWxfZm9yZWlnbikpCmBgYAoKIyMgQW5kIGhvdyBtYW55IG9mIHRoZXNlIGZvcmVpZ24tYm9ybiB3b3JrZXJzIGFyZSBIaXNwYW5pYz8KCmBgYHtyfQppcHVtc19mb29kX3Byb2R1Y3Rpb25fYnlfY291bnR5ICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9mb3JlaWduKSkgJT4lCiAgc2VsZWN0KAogICAgY291bnR5LAogICAgdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzLAogICAgdG90YWxfZm9yZWlnbiwKICAgIHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMKICApICU+JQogIGhlYWQoMzEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzdW1tYXJpemUoc3VtKHRvdGFsX2ZvcmVpZ25faGlzcGFuaWMpKQpgYGAKCiMjIFdoYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmb3JlaWduIHdvcmtlcnMgaW4gdGhlc2UgaW5kdXN0cmllcyBieSBzdGF0ZT8KCmBgYHtyIGFuYWx5c2lzIGVtcGxveW1lbnQgYW5kIENPVklEIHN0YXR1cyBieSBzdGF0ZX0KZm9vZHdvcmtlcnNfYnlfc3RhdGUgPC0gaXB1bXNfZm9vZF9wcm9kdWN0aW9uX2J5X3B1bWEgJT4lCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQogIHN1bW1hcml6ZSgKICAgIHN0YXRlX3RvdGFsX2VtcGxveW1lbnRfc2VsZWN0ZWRfaW5kdXN0cmllcyA9CiAgICAgIHN1bSh0b3RhbF9lbXBsb3llZXMpLAogICAgc3RhdGVfdG90YWxfZm9yZWlnbiA9IHN1bSh0b3RhbF9mb3JlaWduKSwKICAgIHN0YXRlX3BjdF90b3RhbF9mb3JlaWduID0gcm91bmQoCiAgICAgIHN1bSh0b3RhbF9mb3JlaWduKSAvIHN1bSh0b3RhbF9lbXBsb3llZXMpICogMTAwCiAgICApLAogICAgMiwKICAgIHN0YXRlX3RvdGFsX2ZvcmVpZ25faGlzcGFuaWMgPSBzdW0odG90YWxfZm9yZWlnbl9oaXNwYW5pYyksCiAgICBzdGF0ZV9wY3RfdG90YWxfZm9yZWlnbl9oaXNwYW5pYyA9IHJvdW5kKAogICAgICBzdW0odG90YWxfZm9yZWlnbl9oaXNwYW5pYykgLwogICAgICAgIHN1bSh0b3RhbF9lbXBsb3llZXMpICogMTAwCiAgICApLAogICAgMgogICkgJT4lCiAgbXV0YXRlKAogICAgcmFua190b3RhbF9lbXBsb3ltZW50ID0gZGVuc2VfcmFuayhkZXNjKAogICAgICBzdGF0ZV90b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMKICAgICkpLAogICAgcmFua190b3RhbF9mb3JlaWduID0gZGVuc2VfcmFuayhkZXNjKHN0YXRlX3RvdGFsX2ZvcmVpZ24pKSwKICAgIHJhbmtfdG90YWxfZm9yZWlnbl9oaXNwYW5pYyA9IGRlbnNlX3JhbmsoZGVzYyhzdGF0ZV90b3RhbF9mb3JlaWduX2hpc3BhbmljKSkKICApICU+JQogIHNlbGVjdCgKICAgIHN0YXRlLAogICAgc3RhdGVfdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzLAogICAgc3RhdGVfdG90YWxfZm9yZWlnbiwKICAgIHN0YXRlX3BjdF90b3RhbF9mb3JlaWduLAogICAgc3RhdGVfdG90YWxfZm9yZWlnbl9oaXNwYW5pYywKICAgIHN0YXRlX3BjdF90b3RhbF9mb3JlaWduX2hpc3BhbmljLAogICAgcmFua190b3RhbF9lbXBsb3ltZW50LAogICAgcmFua190b3RhbF9mb3JlaWduLAogICAgcmFua190b3RhbF9mb3JlaWduX2hpc3BhbmljCiAgKSAlPiUKICBhcnJhbmdlKGRlc2Moc3RhdGVfdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzKSkKCmZvb2R3b3JrZXJzX2J5X3N0YXRlCmBgYAoKIyMgV2hhdCBwcm9wb3J0aW9uIG9mIHRvdGFsIGZvb2R3b3JrZXIgZW1wbG95bWVudCBkbyB0aGUgdG9wIDEwIHN0YXRlcyBhY2NvdW50IGZvcj8KCmBgYHtyfQpmb29kd29ya2Vyc19ieV9zdGF0ZSAlPiUKICBhcnJhbmdlKGRlc2Moc3RhdGVfdG90YWxfZW1wbG95bWVudF9zZWxlY3RlZF9pbmR1c3RyaWVzKSkgJT4lCiAgaGVhZCgxMCkgJT4lCiAgc3VtbWFyaXplKHN1bShzdGF0ZV90b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMpKQpgYGAKCiMjIyBXaGF0IGlzIHRoZSBkaXN0cmlidXRpb24gb2YgZm9yZWlnbiB3b3JrZXJzIGluIHRoZXNlIGluZHVzdHJpZXMgYnkgc3RhdGU/CgpgYGB7cn0KZm9vZHdvcmtlcnNfYnlfc3RhdGUgJT4lCiAgc3VtbWFyaXplKHN1bShzdGF0ZV90b3RhbF9lbXBsb3ltZW50X3NlbGVjdGVkX2luZHVzdHJpZXMpKQpgYGAKCiMjIyBXaGVyZSBkbyB0aGUgIlJlZCBab25lIiBzdGF0ZXMgc3RhbmQ/CgpgYGAge3J9CnJlZF96b25lIDwtCiAgZGF0YS5mcmFtZSgKICAgICJzdGF0ZSIgPSBjKAogICAgICAiQWxhYmFtYS9BTCIsCiAgICAgICJBcml6b25hL0FaIiwKICAgICAgIkFya2Fuc2FzL0FSIiwKICAgICAgIkNhbGlmb3JuaWEvQ0EiLAogICAgICAiRmxvcmlkYS9GTCIsCiAgICAgICJHZW9yZ2lhL0dBIiwKICAgICAgIklkYWhvL0lEIiwKICAgICAgIklvd2EvSUEiLAogICAgICAiS2Fuc2FzL0tTIiwKICAgICAgIkxvdWlzaWFuYS9MQSIsCiAgICAgICJNaXNzaXNzaXBwaS9NUyIsCiAgICAgICJNaXNzb3VyaS9NTyIsCiAgICAgICJOZXZhZGEvTlYiLAogICAgICAiTm9ydGggQ2Fyb2xpbmEvTkMiLAogICAgICAiTm9ydGggRGFrb3RhL05EIiwKICAgICAgIk9rbGFob21hL09LIiwKICAgICAgIlNvdXRoIENhcm9saW5hL1NDIiwKICAgICAgIlRlbm5lc3NlZS9UTiIsCiAgICAgICJUZXhhcy9UWCIsCiAgICAgICJVdGFoL1VUIiwKICAgICAgIldpc2NvbnNpbi9XSSIKICAgICksCiAgICAicmVkX3pvbmUiID0gVFJVRQogICkKCnJlZF96b25lCmBgYAoKIyMjIEpvaW4gd2l0aCB0aGUgcmVkIHpvbmUgc3RhdGVzIGRhdGEgZnJhbWUKCmBgYHtyfQpmb29kd29ya2Vyc19ieV9zdGF0ZSA8LSBmb29kd29ya2Vyc19ieV9zdGF0ZSAlPiUKICBsZWZ0X2pvaW4ocmVkX3pvbmUsIGJ5ID0gInN0YXRlIikKYGBgCgojIyMgV2hlcmUgZG8gdGhlIFJlZCBab25lIHN0YXRlcyBzdGFuZD8KCmBgYHtyfQpmb29kd29ya2Vyc19ieV9zdGF0ZSAlPiUKICBmaWx0ZXIocmVkX3pvbmUgPT0gVFJVRSkKYGBgCgojIyBFeHBvcnQgdGhlIHN0YXRlcwoKYGBge3J9CndyaXRlX2Nzdihmb29kd29ya2Vyc19ieV9zdGF0ZSwKICAgICAgICAgICJkYXRhL2V4cG9ydGVkL2Zvb2R3b3JrZXJzX2J5X3N0YXRlLmNzdiIpCmBgYAo=